﻿using System.Xml;
using System.IO;

namespace XamlLocalizer.Tools
{
    public class PrettyXmlWriter : XmlTextWriter
    {
        private const int DefaultMaxSignificantLineLength = 80;
        private const int DefaultIndent = 4;
        private const int DefaultAttributesIndent = 4;

        private readonly StringWriter stringWriter;
        private int curElemIndent;

        public static PrettyXmlWriter Create()
        {
            return new PrettyXmlWriter(new StringWriter());
        }

        private PrettyXmlWriter(StringWriter stringWriter) : base(stringWriter)
        {
            this.stringWriter = stringWriter;
            Formatting = Formatting.Indented;
            Indentation = DefaultIndent;
            MaxSignificantLineLength = DefaultMaxSignificantLineLength;
            AttributesIndent = DefaultAttributesIndent;
        }

        public int MaxSignificantLineLength { get; set; }

        public int AttributesIndent { get; set; }

        public string GetXml()
        {
            return stringWriter.GetStringBuilder().ToString();
        }

        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            curElemIndent = -1;
            base.WriteStartElement(prefix, localName, ns);
        }

        public override void WriteStartAttribute(string prefix, string localName, string ns)
        {
            if (GetLastSignificantLineLength() > MaxSignificantLineLength)
            {
                WriteAttributeIndent();
            }
            base.WriteStartAttribute(prefix, localName, ns);
        }

        private void WriteAttributeIndent()
        {
            if (curElemIndent == -1)
            {
                curElemIndent = GetLastLineIndent();
            }

            stringWriter.WriteLine();
            int indent = curElemIndent +  AttributesIndent;
            for (int i = 0; i < indent; i++)
            {
                stringWriter.Write(IndentChar);
            }
        }

        //private int GetLastLineLength()
        //{
        //    var sb = stringWriter.GetStringBuilder();
        //    int len = 0;
        //    for (int i = sb.Length - 1; i >= 0; i--)
        //    {
        //        char c = sb[i];
        //        if (c == '\n' || c == '\r')
        //            break;
        //        len++;
        //    }
        //    return len;
        //}

        private int GetLastSignificantLineLength()
        {
            var sb = stringWriter.GetStringBuilder();
            int len = 0;
            int lastSignificantLen = 0;
            for (int i = sb.Length - 1; i >= 0; i--)
            {
                char c = sb[i];
                if (c == '\n' || c == '\r')
                    break;
                len++;
                if (c != ' ')
                    lastSignificantLen = len;
            }
            return lastSignificantLen;
        }

        private int GetLastLineIndent()
        {
            var sb = stringWriter.GetStringBuilder();
            int len = 0;
            int lastSignificantLen = 0;
            for (int i = sb.Length - 1; i >= 0; i--)
            {
                char c = sb[i];
                if (c == '\n' || c == '\r')
                    break;
                len++;
                if (c != ' ')
                    lastSignificantLen = len;
            }
            return len - lastSignificantLen;
        }
    }
}
